/*
 * buf_PersistentStr.c
 *
 *  Created on: 2012/03/29
 *      Author: guanxiaoying
 */
#include "../../parser/coredef.h"

/*KIND_SYMNAMECTRL	*/
typedef struct _SYMNAMECTRL{
	AST	astSymName;			/* 2 */
	RBTREE	rbtree;
}SYMNAMECTRL, *PSYMNAMECTRL;

#define BufType  PSZ
#define Buffer stLabelBufManager.memoryBlocks
#define Buflen stLabelBufManager.maxRecordNum
#define  bufLenPerBlk  (stLabelBufManager.astMaxNum_Block)

#define TableSize   (sizeof(SYMNAMECTRL))
#define TableType  PSYMNAMECTRL
#define stTable stLabelCtrlManager.memoryBlocks
#define maxTable stLabelCtrlManager.maxRecordNum
#define  maxNumPerBlk  (stLabelCtrlManager.astMaxNum_Block)

/* private field */
static AST              gblSymTreeRoot = 0;
static TABLEMANAGER stLabelCtrlManager = {
//		U4                  usIdx;
		0,
//		PSZ				    con_pszName;    constant
		__FILE__ "_Ctrl",
//		U2					con_usSize;		constant
		TableSize,
//		U2					block_num;	　　　　　　　Reset clear  際　要
		0,
//		S4					astMaxNum_Block;     １回設定のみ
		0,
//		S4					astTabNum_LastPage; 　　　　Reset clear  際　要
		0,
//		S4					astMaxNum_LastPage;     Reset clear  際　要
		0,
//		U4					ulMaxByte;	　　　　　　　　　　クリアしない
		0,
//		U4					con_minPageSize;　　　　　　　　　　constant
		0
};
static TABLEMANAGER stLabelBufManager = {
//		U4                  usIdx;
		0,
//		PSZ				    con_pszName;    constant
		__FILE__,
//		U2					con_usSize;		constant
		1,
//		U2					block_num;	　　　　　　　Reset clear  際　要
		0,
//		S4					astMaxNum_Block;     １回設定のみ
		0,
//		S4					astTabNum_LastPage; 　　　　Reset clear  際　要
		0,
//		S4					astMaxNum_LastPage;     Reset clear  際　要
		0,
//		U4					ulMaxByte;	　　　　　　　　　　クリアしない
		0,
//		U4					con_minPageSize;　　　　　　　　　　constant
		0
};
static VOID resetListener( U4  procid, U2 index )
{
	if( procid == stLabelCtrlManager.u4Idx )
	{
		if( index > 0 && index < MAX_VOLUMN_OF_TABLE )
		{
			stTable[ index-1] = NULL;
		}
	}
}
static TableType core_getTable( AST index )
{
	TableType temp = (TableType)Check_Com( &stLabelCtrlManager, resetListener, index );
	if( temp != NULL ){ return &temp[index%maxNumPerBlk]; } return NULL;
}
static BOOL ClearTable( VOID )
{
	gblSymTreeRoot = 0;
	return Clear_Com( &stLabelCtrlManager );
}
static BOOL ResetTable( VOID )
{
	gblSymTreeRoot = 0;
	return Reset_Com( &stLabelCtrlManager );
}
static BOOL AllocTable( AST astReqArg )
{
	return AllocTable_Com( &stLabelCtrlManager, astReqArg, resetListener );
}

static AST getMaxLineNum( VOID )
{
	return maxTable;
}
/* get the object */
/* get the object */
static VOID resetBufListener( U4  procid, U2 index )
{
	if( procid == stLabelBufManager.u4Idx )
	{
		if( index > 0 && index < MAX_VOLUMN_OF_TABLE )
		{
			Buffer[ index-1] = NULL;
		}
	}
}
static BufType core_getBuf( AST index )
{
	BufType temp = (BufType)Check_Com( &stLabelBufManager, resetBufListener, index );
	if( temp != NULL ){
		return &temp[index%bufLenPerBlk];
	}
	return NULL;
}


static BOOL AllocBuffer( AST astReqArg )
{
	return AllocBuffer_Com( &stLabelBufManager, astReqArg, resetBufListener );
}
//		BOOL (*clear)( VOID );
static BOOL ClearBuffer( VOID )
{
	BOOL bRet1 = ClearTable();
	BOOL bRet2 = Clear_Com( &stLabelBufManager );
	return bRet1 && bRet2;
}
static BOOL ResetBuffer( VOID )
{
	BOOL bRet1 = ResetTable();
	BOOL bRet2 = Reset_Com( &stLabelBufManager );
	return bRet1 && bRet2;
}
static AST getLeft( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astLeftChild;
}
static AST setLeft( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astLeftChild = value;
}
static AST getRight( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astRightChild;
}
static AST setRight( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astRightChild = value;
}
static AST getParent( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astParent;
}
static AST setParent( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.astParent = value;
}
static AST getIndex( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astSymName;
}
static U2 getColor( AST index )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.lColor;
}
static U2 setColor( AST index, U2 value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->rbtree.lColor = value;
}
static ACCESS_RBTREE stAccessRbtree =
{
		AllocTable,
		getMaxLineNum,
		getIndex,
		{
				getLeft,
				setLeft
		},
		{
				getRight,
				setRight
		},
		{
				getParent,
				setParent
		},
		{
				getColor,
				setColor
		}
};

static S4	cmp_sym_str ( AST	astSymName, void* pszStr )
{
	PSZ		pszname;
	PSZ		psznameintree;
	S4 nRet;

	if( astSymName == 0 )
	{
		return RBT_LESS;
	}
	pszname = (PSZ)pszStr;
	if( pszname == 0 || *pszname == '\0' )
	{
		return RBT_FOUND;
	}
	psznameintree = core_getBuf(astSymName);
	if( psznameintree == NULL || *psznameintree == '\0' )
	{
		return RBT_LESS;
	}
	nRet = strcmp( pszname, psznameintree );
	if( nRet > 0 )
	{
		return RBT_LARGER;
	}else if( nRet < 0 )
	{
		return RBT_LESS;
	}
	return RBT_FOUND;
}
/* give up the way that defining get/set function pointer in the struct,
 * because of memory volume.
 */
/*  get method */
static CHAR * getSymStr( AST index )
{
	BufType pTbl = core_getBuf( index );
	if( pTbl == NULL )
	{
		return "";
	}
	return pTbl;
}
/*  set method */
static AST setSymStr( PSZ str )
{

	S4 lenBuf = str_length(str);
	if( lenBuf > 0 && lenBuf < MemGetBlockSize( ))
	{
		AST astNewNode = 0;
		AST astParent = 0;
		S4 nCmpResult = 0;
		if( gblSymTreeRoot > 0 )
		{
			nCmpResult = FindData( &stAccessRbtree, gblSymTreeRoot , str ,&astParent, cmp_sym_str );
			if( nCmpResult == 0 )
			{
				TableType pTbl = core_getTable( astParent );
				if( pTbl == NULL )
				{
					return 0;
				}
				return pTbl->astSymName;
			}
		}
		else
		{
			astParent = 0;
			nCmpResult = 1;
		}

		if ( 0 == AllocBuffer( lenBuf + 1 ) )
		{
			return 0;
		}
		lenBuf = Buflen - lenBuf;
		BufType pTbl = core_getBuf( lenBuf );
		if( pTbl == NULL )
		{
			return 0;
		}
		strcpy(pTbl, str);
		*((PSZ)Buffer[Buflen/bufLenPerBlk]+(Buflen%bufLenPerBlk)) = '\0';
		if( FALSE == InsertData( &stAccessRbtree, nCmpResult, astParent,&gblSymTreeRoot, &astNewNode ))
		{
			return 0;
		}

		((TableType)stTable[astNewNode/maxNumPerBlk] + (astNewNode%maxNumPerBlk))->astSymName = lenBuf;
	}
	else
	{
		if ( 0 == AllocBuffer( lenBuf + 1 ) )
		{
			return 0;
		}
		lenBuf = Buflen;
	}
	return lenBuf;
}
const ACCESS_LABEL_STR stCoreLabelStrAccess = {
		ClearBuffer,
		ResetBuffer,
		getSymStr,
		setSymStr
};
